var game = {

	__animations : [],

	hextypes : {
		"default" : {
			stroke : '#606060',
			fill : '#ffffff'
		},
		"unknown" : {
			stroke : '#c0c0c0',
			fill : '#ffffff',
			glyph : '\uf128',
			font : 'FontAwesome'
		},
		"explore" : {
			stroke : '#a0a0a0',
			fill : '#ffffff',
			glyph : '\uf002',
			font : 'FontAwesome'
		},
		"storage" : {
			stroke : '#606060',
			fill : '#ffffff',
			glyph : '\uf1b3',
			font : 'FontAwesome'
		},
		// natural resources
		"wood" : {
			stroke : '#606060',
			fill : '#ffffff',
			glyph : '\uf1bb',
			font : 'FontAwesome'
		},
		"rock" : {
			stroke : '#606060',
			fill : '#ffffff',
			glyph : '\uf096',
			font : 'FontAwesome'
		},
		"coal" : {
			stroke : '#606060',
			fill : '#ffffff',
			glyph : '\uf0c8',
			font : 'FontAwesome'
		},
		"oil" : {
			stroke : '#606060',
			fill : '#ffffff',
			glyph : '\uf043',
			font : 'FontAwesome'
		},
		"uranium" : {
			stroke : '#606060',
			fill : '#ffffff',
			glyph : '\uf123',
			font : 'FontAwesome'
		},
		"magnetite" : {
			stroke : '#606060',
			fill : '#ffffff',
			glyph : '\uf076',
			font : 'FontAwesome'
		},
		"gold" : {
			stroke : '#606060',
			fill : '#ffffff',
			glyph : '\uf006',
			font : 'FontAwesome'
		},
		// resource production
		"forrestnursery" : {
			stroke : '#606060',
			fill : '#ffffff',
			glyph : '\uf18c',
			font : 'FontAwesome'
		},
		"cementplant" : {
			stroke : '#606060',
			fill : '#ffffff',
			glyph : '\uf042',
			font : 'FontAwesome'
		},
		"cokeoven" : {
			stroke : '#606060',
			fill : '#ffffff',
			glyph : '\uf06d',
			font : 'FontAwesome'
		},
		// energy production
		"powerplant" : {
			stroke : '#606060',
			fill : '#ffffff',
			glyph : '\uf0e7',
			font : 'FontAwesome'
		},
		"waste" : {
			stroke : '#606060',
			fill : '#ffffff',
			glyph : '\uf014',
			font : 'FontAwesome'
		},
		"recycling" : {
			stroke : '#606060',
			fill : '#ffffff',
			glyph : '\uf1b8',
			font : 'FontAwesome'
		},
		"solarplant" : {
			stroke : '#606060',
			fill : '#ffffff',
			glyph : '\uf185',
			font : 'FontAwesome'
		},
		// workforce production
		"refinery" : {
			stroke : '#606060',
			fill : '#ffffff',
			glyph : '\uf0c3',
			font : 'FontAwesome'
		},
		"toolfactory" : {
			stroke : '#606060',
			fill : '#ffffff',
			glyph : '\uf0ad',
			font : 'FontAwesome'
		},
		"unitfactory" : {
			stroke : '#606060',
			fill : '#ffffff',
			glyph : '\uf085',
			font : 'FontAwesome'
		},
		"foundry" : {
			stroke : '#606060',
			fill : '#ffffff',
			glyph : '\uf0c9',
			font : 'FontAwesome'
		},
		// innovation
		"university" : {
			stroke : '#606060',
			fill : '#ffffff',
			glyph : '\uf19d',
			font : 'FontAwesome'
		},
		"innovationcenter" : {
			stroke : '#606060',
			fill : '#ffffff',
			glyph : '\uf0eb',
			font : 'FontAwesome'
		},
		"library" : {
			stroke : '#606060',
			fill : '#ffffff',
			glyph : '\uf02d',
			font : 'FontAwesome'
		},
		// money
		"bank" : {
			stroke : '#606060',
			fill : '#ffffff',
			glyph : '\uf0d6',
			font : 'FontAwesome'
		},
		"coinage" : {
			stroke : '#606060',
			fill : '#ffffff',
			glyph : '\uf1c0',
			font : 'FontAwesome'
		}

	// f077
	// f013
	// f0ae
	// f139
	// f1db
	// f0ec
	// f111
	// f0b0
	},

	edgelen : 30,

	hex : function(grid_x, grid_y, type) {
		if (typeof type === 'undefined')
			type = 'default';
		var hextype = this.hextypes[type];
		if (typeof hextype === 'undefined')
			hextype = this.hextypes['unknown'];
		var ctx = this.ctx;
		var size = this.edgelen;
		var center_x = grid_x * Math.sqrt(3) * size + (grid_y % 2)
				* Math.sqrt(3) * size / 2;
		var center_y = grid_y * size * 3 / 2;
		ctx.strokeStyle = hextype.stroke;
		ctx.fillStyle = hextype.fill;
		ctx.beginPath();
		for (var i = 0; i < 6; ++i) {
			var angle = 2 * Math.PI / 6 * (i + 0.5);
			var x_i = center_x + size * Math.cos(angle);
			var y_i = center_y + size * Math.sin(angle);
			if (i == 0) {
				ctx.moveTo(x_i, y_i);
			} else {
				ctx.lineTo(x_i, y_i);
			}
		}
		ctx.closePath();
		ctx.stroke();
		ctx.fill();
		if (hextype.glyph) {
			ctx.textAlign = 'center';
			ctx.textBaseline = 'middle';
			ctx.font = /* 'bold ' */+(3 / 4 * size) + 'px '
					+ (hextype.font ? hextype.font : 'Helvetica');
			ctx.fillStyle = hextype.stroke;
			ctx.fillText(hextype.glyph, center_x, center_y);
		}
	},

	/**
	 * Draws a single power connector.
	 */
	pc : function(grid_x1, grid_y1, anchor1, grid_x2, grid_y2, anchor2) {
		var ctx = this.ctx;
		var size = this.edgelen;
		// first anchor
		ctx.strokeStyle = '#606060';
		ctx.beginPath();
		var center_x = grid_x1 * Math.sqrt(3) * size + (grid_y1 % 2)
				* Math.sqrt(3) * size / 2;
		var center_y = grid_y1 * size * 3 / 2;
		var angle = 2 * Math.PI / 6 * (anchor1 + 0.5);
		var x_i = center_x + (size * 0.7) * Math.cos(angle);
		var y_i = center_y + (size * 0.7) * Math.sin(angle);
		ctx.arc(x_i, y_i, size * 0.1, 0, 2 * Math.PI);
		ctx.closePath();
		ctx.stroke();
		// second anchor
		ctx.beginPath();
		var center_x2 = grid_x2 * Math.sqrt(3) * size + (grid_y2 % 2)
				* Math.sqrt(3) * size / 2;
		var center_y2 = grid_y2 * size * 3 / 2;
		var angle2 = 2 * Math.PI / 6 * (anchor2 + 0.5);
		var x_i2 = center_x2 + (size * 0.7) * Math.cos(angle2);
		var y_i2 = center_y2 + (size * 0.7) * Math.sin(angle2);
		ctx.arc(x_i2, y_i2, size * 0.1, 0, 2 * Math.PI);
		ctx.closePath();
		ctx.stroke();
		// line
		ctx.beginPath();
		ctx.moveTo(x_i, y_i);
		ctx.lineTo(x_i2, y_i2);
		ctx.closePath();
		ctx.stroke();
	},

	/**
	 * Calculates distance between two points in regular geometry
	 */
	__dist_xy : function(x1, y1, x2, y2) {
		return Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2));
	},

	__opposites : [ [ // 0
	{
		dgx : 1,
		dgy : 1,
		a : 4
	}, {
		dgx : 1,
		dgy : 0,
		a : 2
	} ], [ // 1
	{
		dgx : 1,
		dgy : 1,
		a : 3
	}, {
		dgx : 0,
		dgy : 1,
		a : 5
	} ], [ // 2
	{
		dgx : 0,
		dgy : 1,
		a : 4
	}, {
		dgx : -1,
		dgy : 0,
		a : 0
	} ], [ // 3
	{
		dgx : -1,
		dgy : 0,
		a : 5
	}, {
		dgx : 0,
		dgy : -1,
		a : 1
	} ], [ // 4
	{
		dgx : 0,
		dgy : -1,
		a : 0
	}, {
		dgx : 1,
		dgy : -1,
		a : 2
	} ], [ // 5
	{
		dgx : 1,
		dgy : -1,
		a : 1
	}, {
		dgx : 1,
		dgy : 0,
		a : 3
	} ] ],

	/**
	 * Draws an optimal power line between two arbitrary hexes.
	 */
	pl : function(grid_x1, grid_y1, grid_x2, grid_y2) {
		var size = this.edgelen;
		var center_x1 = grid_x1 * Math.sqrt(3) * size + (grid_y1 % 2)
				* Math.sqrt(3) * size / 2;
		var center_y1 = grid_y1 * size * 3 / 2;
		var center_x2 = grid_x2 * Math.sqrt(3) * size + (grid_y2 % 2)
				* Math.sqrt(3) * size / 2;
		var center_y2 = grid_y2 * size * 3 / 2;
		var ctx = this.ctx;
		var lgx = grid_x1;
		var lgy = grid_y1;
		var la = null, lx = null, ly = null;
		var x_a2 = null, y_a2 = null;
		var min_d = null;
		for (var i = 0; i < 6; ++i) {
			for (var j = 0; j < 6; ++j) {
				var angle1 = 2 * Math.PI / 6 * (i + 0.5);
				var x_i1 = center_x1 + (size * 0.7) * Math.cos(angle1);
				var y_i1 = center_y1 + (size * 0.7) * Math.sin(angle1);
				var angle2 = 2 * Math.PI / 6 * (j + 0.5);
				var x_j2 = center_x2 + (size * 0.7) * Math.cos(angle2);
				var y_j2 = center_y2 + (size * 0.7) * Math.sin(angle2);
				var d = this.__dist_xy(x_i1, y_i1, x_j2, y_j2);
				if (min_d == null || min_d >= d) {
					min_d = d;
					lx = x_i1;
					ly = y_i1;
					x_a2 = x_j2;
					y_a2 = y_j2;
					la = i;
				}
			}
		}
		ctx.beginPath();
		ctx.arc(lx, ly, size * 0.1, 0, 2 * Math.PI);
		ctx.closePath();
		ctx.stroke();
		while (lgx != grid_x2 || lgy != grid_y2) {
			var ops = this.__opposites[la].slice();
			ops.push({
				dgx : 0,
				dgy : 0,
				a : (la + 1) % 6
			});
			ops.push({
				dgx : 0,
				dgy : 0,
				a : (la + 5) % 6
			});
			var min_od = null, min_ox = null, min_oy = null, min_a = null;
			for (var oi = 0; oi < ops.length; ++oi) {
				var op = ops[oi];
				var gy = lgy + op.dgy;
				var gx = lgx + op.dgx + Math.abs(lgy - gy) * (lgy % 2);
				var a = op.a;
				var cx = gx * Math.sqrt(3) * size + (gy % 2) * Math.sqrt(3)
						* size / 2;
				var cy = gy * size * 3 / 2;
				var angle = 2 * Math.PI / 6 * (a + 0.5);
				var ox = cx + (size * 0.7) * Math.cos(angle);
				var oy = cy + (size * 0.7) * Math.sin(angle);
				var od = this.__dist_xy(ox, oy, x_a2, y_a2);
				if (min_od == null || min_od > od) {
					min_gx = gx;
					min_gy = gy;
					min_od = od;
					min_ox = ox;
					min_oy = oy;
					min_a = a;
				}
			}
			ctx.strokeStyle = '#606060';
			ctx.beginPath();
			ctx.moveTo(lx, ly);
			ctx.lineTo(min_ox, min_oy);
			ctx.closePath();
			ctx.stroke();
			ctx.beginPath();
			ctx.arc(min_ox, min_oy, size * 0.1, 0, 2 * Math.PI);
			ctx.closePath();
			ctx.stroke();
			lgx = min_gx;
			lgy = min_gy;
			lx = min_ox;
			ly = min_oy;
			la = min_a;
		}
	},

	tr : function(grid_x1, grid_y1, grid_x2, grid_y2) {
		var size = this.edgelen;
		var center_x1 = grid_x1 * Math.sqrt(3) * size + (grid_y1 % 2)
				* Math.sqrt(3) * size / 2;
		var center_y1 = grid_y1 * size * 3 / 2;
		var center_x2 = grid_x2 * Math.sqrt(3) * size + (grid_y2 % 2)
				* Math.sqrt(3) * size / 2;
		var center_y2 = grid_y2 * size * 3 / 2;
		var min_d = null;
		var a1s = [];
		var a2s = [];
		for (var i = 0; i < 6; ++i) {
			for (var j = 0; j < 6; ++j) {
				var angle1 = 2 * Math.PI / 6 * (i + 0.5);
				var x_i1 = center_x1 + (size * 0.7) * Math.cos(angle1);
				var y_i1 = center_y1 + (size * 0.7) * Math.sin(angle1);
				var angle2 = 2 * Math.PI / 6 * (j + 0.5);
				var x_j2 = center_x2 + (size * 0.7) * Math.cos(angle2);
				var y_j2 = center_y2 + (size * 0.7) * Math.sin(angle2);
				var d = this.__dist_xy(x_i1, y_i1, x_j2, y_j2);
				if (min_d != null && Math.abs(min_d - d) < 0.1) {
					a1s.push(i);
					a2s.push(j);
				} else if (min_d == null || min_d > d) {
					min_d = d;
					a1s = [];
					a1s.push(i);
					a2s = [];
					a2s.push(j);
				}
			}
		}
		// first anchor
		var center_x1 = grid_x1 * Math.sqrt(3) * size + (grid_y1 % 2)
				* Math.sqrt(3) * size / 2;
		var center_y1 = grid_y1 * size * 3 / 2;
		var angle_a11 = 2 * Math.PI / 6 * (a1s[0] + 0.5);
		var x_a11 = center_x1 + (size * 0.7) * Math.cos(angle_a11);
		var y_a11 = center_y1 + (size * 0.7) * Math.sin(angle_a11);
		var angle_a12 = 2 * Math.PI / 6 * (a1s[1] + 0.5);
		var x_a12 = center_x1 + (size * 0.7) * Math.cos(angle_a12);
		var y_a12 = center_y1 + (size * 0.7) * Math.sin(angle_a12);
		// second anchor
		var center_x2 = grid_x2 * Math.sqrt(3) * size + (grid_y2 % 2)
				* Math.sqrt(3) * size / 2;
		var center_y2 = grid_y2 * size * 3 / 2;
		var angle_a21 = 2 * Math.PI / 6 * (a2s[0] + 0.5);
		var x_a21 = center_x2 + (size * 0.7) * Math.cos(angle_a21);
		var y_a21 = center_y2 + (size * 0.7) * Math.sin(angle_a21);
		var angle_a22 = 2 * Math.PI / 6 * (a2s[1] + 0.5);
		var x_a22 = center_x2 + (size * 0.7) * Math.cos(angle_a22);
		var y_a22 = center_y2 + (size * 0.7) * Math.sin(angle_a22);
		var animation = {
			ctx : this.ctx,
			x_a11 : x_a11,
			x_a12 : x_a12,
			x_a21 : x_a21,
			x_a22 : x_a22,
			y_a11 : y_a11,
			y_a12 : y_a12,
			y_a21 : y_a21,
			y_a22 : y_a22,
			d : 60,
			__dist_xy : this.__dist_xy,
			redraw : function() {
				var ctx = this.ctx;
				var x_a11 = this.x_a11;
				var x_a12 = this.x_a12;
				var x_a21 = this.x_a21;
				var x_a22 = this.x_a22;
				var y_a11 = this.y_a11;
				var y_a12 = this.y_a12;
				var y_a21 = this.y_a21;
				var y_a22 = this.y_a22;
				// clear
				ctx.fillStyle = '#ffffff';
				ctx.strokeStyle = '#ffffff';
				ctx.beginPath();
				ctx.moveTo(x_a11, y_a11);
				ctx.lineTo(x_a12, y_a12);
				ctx.lineTo(x_a22, y_a22);
				ctx.lineTo(x_a21, y_a21);
				ctx.closePath();
				ctx.fill();
				ctx.stroke();
				// draw vert lines
				ctx.strokeStyle = '#606060';
				ctx.beginPath();
				ctx.moveTo(x_a11, y_a11);
				ctx.lineTo(x_a21, y_a21);
				ctx.moveTo(x_a11, y_a11);
				ctx.lineTo(x_a12, y_a12);
				ctx.lineTo(x_a22, y_a22);
				ctx.lineTo(x_a21, y_a21);
				ctx.moveTo(x_a12, y_a12);
				ctx.lineTo(x_a22, y_a22);
				ctx.closePath();
				ctx.stroke();
				// draw hor lines
				var dd = this.__dist_xy(x_a11, y_a11, x_a21, y_a21);
				var delta = 4;
				var td = 20;
				for (var d_i = this.d / td; d_i < dd; d_i += delta) {
					var x_i1 = x_a11 + (d_i / dd) * (x_a21 - x_a11);
					var y_i1 = y_a11 + (d_i / dd) * (y_a21 - y_a11);
					var x_i2 = x_a12 + (d_i / dd) * (x_a22 - x_a12);
					var y_i2 = y_a12 + (d_i / dd) * (y_a22 - y_a12);
					ctx.beginPath();
					ctx.moveTo(x_i1, y_i1);
					ctx.lineTo(x_i2, y_i2);
					ctx.closePath();
					ctx.stroke();
				}
				this.d = ((this.d + 1) % (td * delta));
			}
		};
		this.__animations.push(animation);
	},

	redraw_animations : function() {
		for (var i = 0; i < game.__animations.length; ++i) {
			game.__animations[i].redraw();
		}
		var requestAnimationFrame = window.requestAnimationFrame
				|| window.mozRequestAnimationFrame
				|| window.webkitRequestAnimationFrame
				|| window.msRequestAnimationFrame;
		requestAnimationFrame(game.redraw_animations);
	},

	redraw : function() {
		game.hex(0, 0);
		game.hex(1, 0);
		game.hex(0, 1);
		game.hex(1, 1, 'unknown');
		game.hex(-1, 1, 'explore');
		// storage
		game.hex(-2, 0, "storage");
		// resources
		game.hex(0, 2, 'wood');
		game.hex(1, 2, "rock");
		game.hex(0, 3, "coal");
		game.hex(1, 3, "oil");
		game.hex(0, 4, "uranium");
		game.hex(1, 4, "magnetite");
		game.hex(0, 5, "gold");
		// resource production
		game.hex(-3, 2, 'forrestnursery');
		game.hex(-4, 2, 'cementplant');
		game.hex(-3, 3, 'cokeoven');
		game.hex(-4, 3, 'foundry');
		// energy
		game.hex(4, 0, 'powerplant');
		game.hex(5, 0, 'waste');
		game.hex(4, 1, 'recycling');
		game.hex(5, 1, 'solarplant');
		// workforce production
		game.hex(7, 0, 'unitfactory');
		game.hex(8, 0, 'refinery');
		game.hex(7, 1, 'toolfactory');
		// innovation
		game.hex(6, 3, 'university');
		game.hex(7, 4, 'innovationcenter');
		game.hex(7, 3, 'library');
		// money
		game.hex(4, 4, 'bank');
		game.hex(4, 5, 'coinage');

		// power connectors - between hexes
		game.hex(6, -4, 'powerplant');
		game.hex(5, -4);
		for (var i = 6; i <= 7; ++i) {
			for (var j = -5; j <= -3; ++j) {
				if (i != 6 || j != -4) {
					game.hex(i, j);
				}
			}
		}
		// 0 => 4(dx=1,dy=1) || 2(dx=1,dy=0)
		game.pc(6, -4, 0, 7, -3, 4);
		game.pc(6, -4, 0, 7, -4, 2);
		// 1 => 3(dx=1,dy=1) || 5(dx=0,dy=1)
		game.pc(6, -4, 1, 7, -3, 3);
		game.pc(6, -4, 1, 6, -3, 5);
		// 2 => 4(dx=0,dy=1) || 0(dx=-1,dy=0)
		game.pc(6, -4, 2, 6, -3, 4);
		game.pc(6, -4, 2, 5, -4, 0);
		// 3 => 5(dx=-1,dy=0) || 1(dx=0,dy=-1)
		game.pc(6, -4, 3, 5, -4, 5);
		game.pc(6, -4, 3, 6, -5, 1);
		// 4 => 0(dx=0,dy=-1) || 2(dx=1,dy=-1)
		game.pc(6, -4, 4, 6, -5, 0);
		game.pc(6, -4, 4, 7, -5, 2);
		// 5 => 1(dx=1,dy=-1) || 3(dx=1,dy=0)
		game.pc(6, -4, 5, 7, -5, 1);
		game.pc(6, -4, 5, 7, -4, 3);

		// power connectors - inside a hex
		game.pc(6, -4, 0, 6, -4, 1);
		game.pc(6, -4, 1, 6, -4, 2);
		game.pc(6, -4, 2, 6, -4, 3);
		game.pc(6, -4, 3, 6, -4, 4);
		game.pc(6, -4, 4, 6, -4, 5);
		game.pc(6, -4, 5, 6, -4, 0);

		// power line
		for (var i = -4; i <= 3; ++i) {
			for (var j = -7; j <= -3; ++j) {
				game.hex(i, j);
			}
		}
		game.hex(0, -6, 'powerplant');
		game.hex(-3, -3, 'unitfactory');
		game.pl(0, -6, -3, -3);

		// transport line
		// game.hex(1, -5, 'coal');
		// game.tr(1, -5, 0, -6);
	}

};

$(document).ready(function() {
	var resizeCanvas = function() {
		var canvas = $("canvas")[0];
		var width = canvas.width = game.screenwidth = window.innerWidth;
		var height = canvas.height = game.screenheight = window.innerHeight;
		var ctx = canvas.getContext("2d");
		ctx.translate(width / 2, height / 2);
		game.redraw();
		game.redraw_animations();
	};
	game.ctx = $("canvas")[0].getContext("2d");
	window.addEventListener('resize', resizeCanvas, false);
	resizeCanvas();
});
